//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
#include "i2c_bsp.h"
#include "gd32f4xx.h"
#include "gd32f4xx_i2c.h"
#include "gd32f4xx_misc.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

#ifndef NULL
#define NULL           ((void*)0)
#endif

/*I2C主模式下的状态码枚举*/
typedef enum
{
    I2C_Master_Start = 0,      //启动信号
    I2C_Master_Restart,        //重复启动信号
    I2C_Master_Write_Addr,     //写地址有应答
    I2C_Master_Read_Addr,      //读地址有应答
    I2C_Master_Send_Cmd,       //写命令有应答
    I2C_Master_Send_Data,      //写数据有应答
    I2C_Master_Receive_Data,   //读数据
    I2C_Master_DMA_Send_End,   //DMA发送结束
    I2C_Master_DMA_Receive_End,//DMA接收结束
}WHT_I2C_Master_State_Code_enum;

typedef struct
{
    void (*GPIO_Init_CB)(void);//引脚必须开漏模式
}WHT_I2C_GPIO_t;

/*软I2C总线结构体*/
typedef struct
{
    WHT_I2C_BUS_t Info;          //总线信息
    unsigned int Delay_Count;    //延迟时间
    unsigned int I2C_BUS;        //总线外设
    WHT_I2C_GPIO_t GPIO;         //总线GPIO
    WHT_I2C_Cache_t* Cache;      //外设缓存,由外部设备提供
    WHT_I2C_Master_State_Code_enum Master_State_Code;//状态机形式
    WHT_DMA_Config_t DMA_Send_Config;   //DMA发送配置
    WHT_DMA_Config_t DMA_Receive_Config;//DMA接收配置
}WHT_I2C_BUS_Private_t;

static WHT_I2C_BUS_Private_t* WHT_I2C_BUS[3];//I2C总线3个

#define WHT_BUS        ((WHT_I2C_BUS_Private_t*)bus)


/*I2C状态码检查*/
static void WHT_I2C_BSP_Check_Error_Code(WHT_I2C_BUS_t* bus)
{
    unsigned int error_code;

    error_code = I2C_STAT0(WHT_BUS->I2C_BUS);
    error_code &= I2C_STAT0_AERR|I2C_STAT0_BERR|I2C_STAT0_SMBTO|I2C_STAT0_PECERR|I2C_STAT0_OUERR|I2C_STAT0_LOSTARB;
    if (error_code != RESET)
    {
        if (error_code & I2C_STAT0_AERR)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_AERR);
			*(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_Slave_No_ACK;
        }
        else if (error_code & I2C_STAT0_BERR)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_BERR);
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_BUS_Error;
        }
        else if (error_code & I2C_STAT0_SMBTO)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_SMBTO);
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_Tx_Send_Error;
        }
        else if (error_code & I2C_STAT0_PECERR)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_PECERR);
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_Other_Error;
        }
        else if (error_code & I2C_STAT0_OUERR)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_OUERR);
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_Rx_Over_Error;
        }
        else if (error_code & I2C_STAT0_LOSTARB)
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_LOSTARB);
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_ARLO_Error;
        }
    }
}
/*I2C发送起始信号*/
static void WHT_I2C_BSP_Send_Start(WHT_I2C_BUS_t* bus)
{
    i2c_enable(WHT_BUS->I2C_BUS);//使能i2c
    i2c_start_on_bus(WHT_BUS->I2C_BUS);//Send i2c Start
}
/*I2C发送从设备地址并写操作*/
static void WHT_I2C_BSP_Send_Slave_Addr_Write(WHT_I2C_BUS_t* bus)
{
    do
    {
        if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_SBSEND) == SET)//EV5 i2c start
        {
            i2c_master_addressing(WHT_BUS->I2C_BUS, WHT_BUS->Cache->Addr_7Bit << 1, I2C_TRANSMITTER);
            break;
        }
        WHT_I2C_BSP_Check_Error_Code(bus);
        if (WHT_BUS->Info.State != I2C_No_Error)
            break;
    } while (1);
}
/*I2C发送从设备地址并读操作*/
static void WHT_I2C_BSP_Send_Slave_Addr_Read(WHT_I2C_BUS_t* bus)
{
    do
    {
        if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_SBSEND) == SET)//EV5 i2c start
        {
            i2c_master_addressing(WHT_BUS->I2C_BUS, WHT_BUS->Cache->Addr_7Bit << 1, I2C_RECEIVER);
            break;
        }
        WHT_I2C_BSP_Check_Error_Code(bus);
        if (WHT_BUS->Info.State != I2C_No_Error)
            break;
    } while (1);
}
/*I2C发送从设备命令*/
static void WHT_I2C_BSP_Send_Slave_Cmd(WHT_I2C_BUS_t* bus)
{
    do
    {
        if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND) == SET)//EV6 send addr have ack
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND);
            while(!i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_TBE));
            break;
        }
        WHT_I2C_BSP_Check_Error_Code(bus);
        if (WHT_BUS->Info.State != I2C_No_Error)
            return;
    } while (1);

    for (char i = 0; i < WHT_BUS->Cache->Cmd_Count; i++)
    {
        i2c_data_transmit(WHT_BUS->I2C_BUS, WHT_BUS->Cache->Cmd[i]);
        do
        {
            if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_TBE) == SET)//EV8_2 send data have ack
                break;
            WHT_I2C_BSP_Check_Error_Code(bus);
            if (WHT_BUS->Info.State != I2C_No_Error)
                return;
        } while (1);
    }
}
/*I2C发送数据*/
static void WHT_I2C_BSP_Send_Data(WHT_I2C_BUS_t* bus)
{
    for (unsigned int i = 0; i < WHT_BUS->Cache->Buffer_Count; i++)
    {
        i2c_data_transmit(WHT_BUS->I2C_BUS, WHT_BUS->Cache->Buffer[i]);
        do
        {
            if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_TBE) == SET)//EV8_2 send data have ack
                break;
            WHT_I2C_BSP_Check_Error_Code(bus);
            if (WHT_BUS->Info.State != I2C_No_Error)
                return;
        } while (1);
    }
}
/*I2C读取数据*/
static void WHT_I2C_BSP_Receive_Data(WHT_I2C_BUS_t* bus)
{
    if (WHT_BUS->Cache->Buffer_Count == 0)
    {
        i2c_stop_on_bus(WHT_BUS->I2C_BUS);//Last Data Send
        return;
    }
    WHT_I2C_BSP_Send_Start(bus);//Send i2c restart
    WHT_I2C_BSP_Send_Slave_Addr_Read(bus);//send read slave
    if (WHT_BUS->Info.State != I2C_No_Error)
    {
        i2c_stop_on_bus(WHT_BUS->I2C_BUS);//Last Data Send
        return;
    }
    do
    {
        if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND) == SET)//EV6 read addr have ack
        {
            i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND);
            break;
        }
        WHT_I2C_BSP_Check_Error_Code(bus);
        if (WHT_BUS->Info.State != I2C_No_Error)
        {
            i2c_stop_on_bus(WHT_BUS->I2C_BUS);//Last Data Send
            return;
        }
    } while (1);
    if (WHT_BUS->Cache->Buffer_Count == 1)
    {
        i2c_stop_on_bus(WHT_BUS->I2C_BUS);
        do
        {
            if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_RBNE) == SET)//EV7 receive data
            {
                WHT_BUS->Cache->Buffer[0] = i2c_data_receive(WHT_BUS->I2C_BUS);
                break;
            }
        } while (1);
    }
    else
    {
        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_ENABLE);
        for (unsigned int i = 0; i < WHT_BUS->Cache->Buffer_Count; i++)
        {
            do
            {
                if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_RBNE) == SET)//EV7 receive data
                {
                    WHT_BUS->Cache->Buffer[i] = i2c_data_receive(WHT_BUS->I2C_BUS);
                    if ((i+2) == WHT_BUS->Cache->Buffer_Count)
                    {
                        while(!i2c_flag_get(I2C0, I2C_FLAG_BTC));
                        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_DISABLE);
                    }
                    break;
                }
            } while (1);
        }
        i2c_stop_on_bus(WHT_BUS->I2C_BUS);
    }
}


/*I2C回调用户的中断函数*/
static void WHT_I2C_BSP_User_IT_Callback(WHT_I2C_BUS_Private_t* BUS)
{
    *(WHT_I2C_BUS_Lock_enum*)&BUS->Info.Mutex = I2C_Unlock;
    if (BUS->Cache->Dir == I2C_Write)
    {
        if (BUS->Cache->Write_Finish_IT_CB != NULL)
            BUS->Cache->Write_Finish_IT_CB();
    }
    else
    {
        if (BUS->Cache->Read_Finish_IT_CB != NULL)
            BUS->Cache->Read_Finish_IT_CB();
    }
}
/*I2C DMA发送和接收回调函数*/
static void WHT_I2C_BSP_DMA_Send_Receive_Callback(WHT_I2C_BUS_Private_t* BUS)
{
    if (BUS->Master_State_Code == I2C_Master_DMA_Receive_End)//DMA Receive End
    {
        i2c_stop_on_bus(BUS->I2C_BUS);               //Send Stop
        i2c_dma_config(BUS->I2C_BUS, I2C_DMA_OFF);
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//Off All Interrupt
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV);
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
        i2c_ack_config(BUS->I2C_BUS, I2C_ACK_DISABLE);//OFF ACK
        BUS->Master_State_Code = I2C_Master_Start;   //Reset I2C State
        WHT_I2C_BSP_User_IT_Callback(BUS);
    }
    else
    {
        if (BUS->DMA_Send_Config.Info->State == TRx_TC)
        {
            i2c_dma_config(BUS->I2C_BUS, I2C_DMA_OFF);     //OFF DMA请求
            i2c_interrupt_enable(BUS->I2C_BUS, I2C_INT_EV);//ON IT_Event
        }
        else
        {
            i2c_stop_on_bus(BUS->I2C_BUS);                 //Send Stop
            i2c_dma_config(BUS->I2C_BUS, I2C_DMA_OFF);     //OFF DMA请求
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//Off All Interrupt
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV);
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
            BUS->Master_State_Code = I2C_Master_Start;     //Reset I2C State
            *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_Other_Error;//I2C Idle
            WHT_I2C_BSP_User_IT_Callback(BUS);
        }
    }
}
static void WHT_I2C1_BSP_DMA_Send_Receive_Callback(void)
{
    WHT_I2C_BSP_DMA_Send_Receive_Callback(WHT_I2C_BUS[0]);
}
static void WHT_I2C2_BSP_DMA_Send_Receive_Callback(void)
{
    WHT_I2C_BSP_DMA_Send_Receive_Callback(WHT_I2C_BUS[1]);
}
static void WHT_I2C3_BSP_DMA_Send_Receive_Callback(void)
{
    WHT_I2C_BSP_DMA_Send_Receive_Callback(WHT_I2C_BUS[2]);
}


/*I2C阻塞读写*/
static void WHT_I2C_BUS_Read_Write(WHT_I2C_BUS_t* bus, WHT_I2C_Cache_t* cache)
{
    unsigned int wait_i2c_stop_send_over;/*当发送stop后关闭i2c则不会立即关闭i2c的此时在向外发送stop信号*/

    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Lock;
    *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;
    WHT_BUS->Cache = cache;

    //检测总线状态
    wait_i2c_stop_send_over = WHT_BUS->Delay_Count;
    while (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_I2CBSY) == SET)
    {
        if (wait_i2c_stop_send_over-- == 0)
        {
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_BUS_Error;
            *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
            return;
        }
    }
    
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_BUF);
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_EV );
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_ERR);

    WHT_I2C_BSP_Send_Start(bus);           //发送开始信号
    WHT_I2C_BSP_Send_Slave_Addr_Write(bus);//发送设备地址
    if (WHT_BUS->Info.State != I2C_No_Error)
        goto Send_Over;
    WHT_I2C_BSP_Send_Slave_Cmd(bus);       //发送命令
    if (WHT_BUS->Info.State != I2C_No_Error)
        goto Send_Over;
    if (WHT_BUS->Cache->Dir == I2C_Write)    //发送数据
    {
        WHT_I2C_BSP_Send_Data(bus);
    }
    else                 //接收数据
    {
        WHT_I2C_BSP_Receive_Data(bus);
        goto Receive_Over;
    }
Send_Over:
    i2c_stop_on_bus(WHT_BUS->I2C_BUS);//send stop
Receive_Over:
    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
}
/*I2C中断读写*/
static void WHT_I2C_BUS_Read_Write_IT(WHT_I2C_BUS_t* bus, WHT_I2C_Cache_t* cache)
{
    unsigned int wait_i2c_stop_send_over;/*当发送stop后关闭i2c则不会立即关闭i2c的此时在向外发送stop信号*/

    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Lock;
    *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;
    WHT_BUS->Cache = cache;

    if (WHT_BUS->Cache->Cmd_Count < 1)
    {
        *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_Other_Error;
        *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
        return;
    }
	
    //默认此设备的I2C工作在从模式,跳出从模式只需要发送I2C起始信号即可
    //检测总线状态  
    wait_i2c_stop_send_over = WHT_BUS->Delay_Count;
    while (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_I2CBSY) == SET)
    {
        if (wait_i2c_stop_send_over-- == 0)
        {
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_BUS_Error;
            *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
            return;
        }
    }

    WHT_BUS->Master_State_Code = I2C_Master_Start;
    i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_EV);
    i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_ERR);
    WHT_I2C_BSP_Send_Start(bus);
}
/*I2C DMA读写*/
static void WHT_I2C_BUS_Read_Write_DMA(WHT_I2C_BUS_t* bus, WHT_I2C_Cache_t* cache)
{
    unsigned int wait_i2c_stop_send_over;/*当发送stop后关闭i2c则不会立即关闭i2c的此时在向外发送stop信号*/
    dma_single_data_parameter_struct DMA_InitStruct =
    {
        //.periph_addr            = (unsigned int)0,            //外设地址
        //.memory0_addr           = (unsigned int)0,            //存储器地址
        //.direction              = DMA_MEMORY_TO_PERIPH,       //M->P
        //.number                 = 0,                          //传输个数
        .circular_mode          = DMA_CIRCULAR_MODE_DISABLE,  //单次模式
        .periph_inc             = DMA_PERIPH_INCREASE_DISABLE,//外设地址不递增
        .memory_inc             = DMA_MEMORY_INCREASE_ENABLE, //存储器地址递增
        .periph_memory_width    = DMA_PERIPH_WIDTH_8BIT,      //外设数据大小为字节
        .priority               = DMA_PRIORITY_LOW,           //优先级最低
    };

    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Lock;
    *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;
    WHT_BUS->Cache = cache;
    
    if ((WHT_BUS->Cache->Dir == I2C_Write) && (WHT_BUS->Cache->Buffer_Count == 0))
    {
        WHT_I2C_BUS_Read_Write(bus, cache);
        return;
    }
    else if ((WHT_BUS->Cache->Dir == I2C_Read) && (WHT_BUS->Cache->Buffer_Count <= 1))
    {
        WHT_I2C_BUS_Read_Write(bus, cache);
        return;
    }
    
    DMA_InitStruct.periph_addr = WHT_BUS->I2C_BUS + 0x10U;//外设基地址
    DMA_InitStruct.memory0_addr = (unsigned int)WHT_BUS->Cache->Buffer;//数据源首地址
    DMA_InitStruct.number = WHT_BUS->Cache->Buffer_Count;              //传输数据个数
    if (WHT_BUS->Cache->Dir == I2C_Write)
    {
        DMA_InitStruct.direction = DMA_MEMORY_TO_PERIPH;                   //传输方向
        WHT_BUS->DMA_Send_Config.DMA_InitStruct = &DMA_InitStruct;

        while (WHT_BUS->DMA_Send_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
        WHT_BUS->DMA_Send_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
        WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Send_Config);      //配置当前DMA
    }
    else
    {
        DMA_InitStruct.direction = DMA_PERIPH_TO_MEMORY;                   //传输方向
        WHT_BUS->DMA_Receive_Config.DMA_InitStruct = &DMA_InitStruct;
        while (WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex == SET);//等待没有外设使用此通道的DMA
        WHT_BUS->DMA_Receive_Config.Info->BSP_Mutex = SET;         //DMA通道上锁
        WHT_DMA_BSP.WHT_Config(&WHT_BUS->DMA_Receive_Config);      //配置当前DMA
    }

    //检测总线状态
    wait_i2c_stop_send_over = WHT_BUS->Delay_Count;
    while (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_I2CBSY) == SET)
    {
        if (wait_i2c_stop_send_over-- == 0)
        {
            WHT_DMA_BSP.WHT_Close(WHT_BUS->Cache->Dir == I2C_Write ? &WHT_BUS->DMA_Send_Config : &WHT_BUS->DMA_Receive_Config);//关闭DMA
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_BUS_Error;
            *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
            return;
        }
    }

    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_BUF);
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_EV );
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_ERR);

    WHT_I2C_BSP_Send_Start(bus);           //发送开始信号
    WHT_I2C_BSP_Send_Slave_Addr_Write(bus);//发送设备地址
    if (WHT_BUS->Info.State != I2C_No_Error)
        goto error;
    WHT_I2C_BSP_Send_Slave_Cmd(bus);       //发送命令
    if (WHT_BUS->Info.State != I2C_No_Error)
        goto error;
    
    if (WHT_BUS->Cache->Dir == I2C_Write)  //发送数据
    {
        WHT_BUS->Master_State_Code = I2C_Master_DMA_Send_End;//DMA Send End
        i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_ERR);//ON IT Error
        i2c_dma_config(WHT_BUS->I2C_BUS, I2C_DMA_ON);      //使能DMA请求
    }
    else                                   //接收数据
    {
        WHT_I2C_BSP_Send_Start(bus);//Send i2c restart
        WHT_I2C_BSP_Send_Slave_Addr_Read(bus);//send read slave
        if (WHT_BUS->Info.State != I2C_No_Error)
        {
            goto error;
        }
        do
        {
            if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND) == SET)//EV6 read addr have ack
            {
                i2c_flag_clear(WHT_BUS->I2C_BUS, I2C_FLAG_ADDSEND);
                break;
            }
            WHT_I2C_BSP_Check_Error_Code(bus);
            if (WHT_BUS->Info.State != I2C_No_Error)
            {
                goto error;
            }
        } while (1);
    
        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_ENABLE);       //ON Send ACK
        WHT_BUS->Master_State_Code = I2C_Master_DMA_Receive_End;//DMA Receive End
        i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_ERR);    //ON IT Error
        i2c_dma_config(WHT_BUS->I2C_BUS, I2C_DMA_ON);           //ON DMA请求
    }
    return;
error:
    i2c_stop_on_bus(WHT_BUS->I2C_BUS);//send stop
    WHT_DMA_BSP.WHT_Close(WHT_BUS->Cache->Dir == I2C_Write ? &WHT_BUS->DMA_Send_Config : &WHT_BUS->DMA_Receive_Config);
    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
}
/*I2C功能使能控制*/
static void WHT_I2C_BSP_Receive_Cmd(WHT_I2C_BUS_t* bus, ControlStatus NewState)
{
    if (NewState == ENABLE)
    {
        i2c_enable(WHT_BUS->I2C_BUS);
        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_ENABLE);
    }
    else
    {
        i2c_disable(WHT_BUS->I2C_BUS);
        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_DISABLE);
    }
}


/*I2C总线配置*/
static void WHT_I2C_BUS_Config(WHT_I2C_BUS_t* bus)
{
    WHT_BUS->Delay_Count = (unsigned int)(((float)(WHT_BUS->Info.Config.Sys_Rate_Hz))/((float)(WHT_BUS->Info.Config.I2C_Rate_Hz)));//延迟时间
    
    /*I2C相关GPIO初始化*/
    WHT_BUS->GPIO.GPIO_Init_CB();

    // 时钟 频率 占空比
    i2c_clock_config(WHT_BUS->I2C_BUS, WHT_BUS->Info.Config.I2C_Rate_Hz, I2C_DTCY_2);
    // 模式（I2C）、地址格式（7位）、自身地址（0x32）
    i2c_mode_addr_config(WHT_BUS->I2C_BUS, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, 0x32);
    // 禁用ACK应答
    i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_DISABLE);

    if (1)//Master Mode
    {
		i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_DISABLE);   //关闭ACK
        i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_BUF);//关闭所有中断
        i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_EV );
        i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_ERR);
    }
    else//从模式下不使用DMA
    {
        i2c_ack_config(WHT_BUS->I2C_BUS, I2C_ACK_ENABLE);   //开启ACK
        i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_BUF);//开启所有中断
        i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_EV );
        i2c_interrupt_enable(WHT_BUS->I2C_BUS, I2C_INT_ERR);
        i2c_enable(WHT_BUS->I2C_BUS); //使能iic
    }
}
/*I2C中断优先级配置*/
static void WHT_I2C_BUS_NVIC_Configuration(WHT_I2C_BUS_t* bus)
{
    /* 配置中断源 */
    if (strcmp(WHT_BUS->Info.Name, WHT_I2C1_Name) == 0)
    {
		NVIC_SetPriority(I2C0_EV_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C0_EV_IRQn);

		NVIC_SetPriority(I2C0_ER_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C0_ER_IRQn);
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_I2C2_Name) == 0)
    {
		NVIC_SetPriority(I2C1_EV_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C1_EV_IRQn);

		NVIC_SetPriority(I2C1_ER_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C1_ER_IRQn); 
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_I2C3_Name) == 0)
    {
#if defined (GD32F450) || defined (GD32F470) || defined (GD32F405) || defined (GD32F425) || defined (GD32F407) || defined (GD32F427)
		NVIC_SetPriority(I2C2_EV_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C2_EV_IRQn);

		NVIC_SetPriority(I2C2_ER_IRQn, WHT_BUS->Info.Config.IT_PreemptionPriority);
		NVIC_EnableIRQ(I2C2_ER_IRQn);
#endif
    }
}
/*总线初始化*/
static void WHT_I2C_BUS_Init(WHT_I2C_BUS_t* bus)
{
    if (strcmp(WHT_BUS->Info.Name, WHT_I2C1_Name) == 0)
    {
        WHT_BUS->I2C_BUS = I2C0;
        rcu_periph_clock_enable(RCU_I2C0);
        WHT_I2C_BUS[0] = (WHT_I2C_BUS_Private_t*)bus;
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_I2C2_Name) == 0)
    {
        WHT_BUS->I2C_BUS = I2C1;
        rcu_periph_clock_enable(RCU_I2C1);
        WHT_I2C_BUS[1] = (WHT_I2C_BUS_Private_t*)bus;
    }
    else if (strcmp(WHT_BUS->Info.Name, WHT_I2C3_Name) == 0)
    {
        WHT_BUS->I2C_BUS = I2C2;
        rcu_periph_clock_enable(RCU_I2C2);
        WHT_I2C_BUS[2] = (WHT_I2C_BUS_Private_t*)bus;
    }
    else
        return;

    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
    *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;    
    WHT_BUS->Cache = NULL;
    WHT_BUS->DMA_Send_Config.IT_Callback = NULL;
    WHT_BUS->DMA_Receive_Config.IT_Callback = NULL;
    WHT_BUS->Master_State_Code = I2C_Master_Start;

    if (1)//这里是I2C Master Mode
    {
        if (strcmp(WHT_BUS->Info.Name, WHT_I2C1_Name) == 0)
        {
            WHT_BUS->DMA_Send_Config.Periph = Periph_I2C1_TX_1;
            WHT_BUS->DMA_Send_Config.Stream = Stream_I2C1_TX_1;
            WHT_BUS->DMA_Send_Config.Channel = Channel_I2C1_TX_1;
            WHT_BUS->DMA_Send_Config.IT_Callback = WHT_I2C1_BSP_DMA_Send_Receive_Callback;
            WHT_BUS->DMA_Receive_Config.Periph = Periph_I2C1_RX_1;
            WHT_BUS->DMA_Receive_Config.Stream = Stream_I2C1_RX_1;
            WHT_BUS->DMA_Receive_Config.Channel = Channel_I2C1_RX_1;
            WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_I2C1_BSP_DMA_Send_Receive_Callback;
        }
        else if (strcmp(WHT_BUS->Info.Name, WHT_I2C2_Name) == 0)
        {
            WHT_BUS->DMA_Send_Config.Periph = Periph_I2C2_TX;
            WHT_BUS->DMA_Send_Config.Stream = Stream_I2C2_TX;
            WHT_BUS->DMA_Send_Config.Channel = Channel_I2C2_TX;
            WHT_BUS->DMA_Send_Config.IT_Callback = WHT_I2C2_BSP_DMA_Send_Receive_Callback;
            WHT_BUS->DMA_Receive_Config.Periph = Periph_I2C2_RX_1;
            WHT_BUS->DMA_Receive_Config.Stream = Stream_I2C2_RX_1;
            WHT_BUS->DMA_Receive_Config.Channel = Channel_I2C2_RX_1;
            WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_I2C2_BSP_DMA_Send_Receive_Callback;
        }
        else if (strcmp(WHT_BUS->Info.Name, WHT_I2C3_Name) == 0)
        {
            WHT_BUS->DMA_Send_Config.Periph = Periph_I2C3_TX;
            WHT_BUS->DMA_Send_Config.Stream = Stream_I2C3_TX;
            WHT_BUS->DMA_Send_Config.Channel = Channel_I2C3_TX;
            WHT_BUS->DMA_Send_Config.IT_Callback = WHT_I2C3_BSP_DMA_Send_Receive_Callback;
            WHT_BUS->DMA_Receive_Config.Periph = Periph_I2C3_RX;
            WHT_BUS->DMA_Receive_Config.Stream = Stream_I2C3_RX;
            WHT_BUS->DMA_Receive_Config.Channel = Channel_I2C3_RX;
            WHT_BUS->DMA_Receive_Config.IT_Callback = WHT_I2C3_BSP_DMA_Send_Receive_Callback;
        }
        WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Send_Config);
        WHT_DMA_BSP.WHT_Register(&WHT_BUS->DMA_Receive_Config);
        i2c_dma_last_transfer_config(WHT_BUS->I2C_BUS, I2C_DMALST_ON);
    }
    //从模式下不使用DMA
    WHT_I2C_BUS_NVIC_Configuration(bus);
    WHT_I2C_BUS_Config(bus);
}

/*总线速率设置*/
static void WHT_I2C_BUS_Set_Rate(WHT_I2C_BUS_t* bus)
{
    WHT_I2C_BUS_Config(bus);
}
/*总线从设备个数*/
static char WHT_I2C_BUS_Scan_Mount_Count(WHT_I2C_BUS_t* bus)
{
    unsigned int wait_i2c_stop_send_over;/*当发送stop后关闭i2c则不会立即关闭i2c的此时在向外发送stop信号*/
    char i2c_slave_count = 0;
    WHT_I2C_Cache_t cache = {0};

    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Lock;
    *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;
    WHT_BUS->Cache = &cache;
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_BUF);
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_EV );
    i2c_interrupt_disable(WHT_BUS->I2C_BUS, I2C_INT_ERR);
    //检测总线状态
    wait_i2c_stop_send_over = WHT_BUS->Delay_Count;
    do
    {
        if (i2c_flag_get(WHT_BUS->I2C_BUS, I2C_FLAG_I2CBSY) != RESET)
        {
            if (wait_i2c_stop_send_over-- == 0)
            {
                *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_BUS_Error;
                *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
                return i2c_slave_count;
            }
        }
        else
            break;
    } while (1);
    do
    {
        WHT_I2C_BSP_Send_Start(bus);           //发送开始信号
        WHT_I2C_BSP_Send_Slave_Addr_Write(bus);//发送设备地址
        if (WHT_BUS->Info.State != I2C_No_Error)
            break;
        WHT_I2C_BSP_Send_Slave_Cmd(bus);       //发送命令
        i2c_stop_on_bus(WHT_BUS->I2C_BUS);     //发送结束信号 
        if (WHT_BUS->Info.State == I2C_No_Error)
            i2c_slave_count++;
        else if (WHT_BUS->Info.State == I2C_Slave_No_ACK)
            *(WHT_I2C_BUS_State_enum*)&WHT_BUS->Info.State = I2C_No_Error;
        else
            break;
        if (WHT_BUS->Cache->Addr_7Bit++ == (0xff >> 1))
            break;
    } while (1);
    *(WHT_I2C_BUS_Lock_enum*)&WHT_BUS->Info.Mutex = I2C_Unlock;
    return i2c_slave_count;
}
/*注册软件I2C总线*/
static WHT_I2C_BUS_t* WHT_I2C_BUS_Register(char* name, WHT_I2C_BUS_Config_t* config, void (*gpio_init_callback)(void))
{
    char Pos;

    if (((strcmp(name, WHT_I2C1_Name) == 0)) && (WHT_I2C_BUS[0] == NULL))
        Pos = 0;
    else if (((strcmp(name, WHT_I2C2_Name) == 0)) && (WHT_I2C_BUS[1] == NULL))
        Pos = 1;
    else if (((strcmp(name, WHT_I2C3_Name) == 0)) && (WHT_I2C_BUS[2] == NULL))
        Pos = 2;
    else
        return NULL;

    WHT_I2C_BUS[Pos] = malloc(sizeof(WHT_I2C_BUS_Private_t));
    if (WHT_I2C_BUS[Pos])
    {
        WHT_I2C_BUS[Pos]->Info.Name = name;
        WHT_I2C_BUS[Pos]->GPIO.GPIO_Init_CB = gpio_init_callback;
        memcpy(&WHT_I2C_BUS[Pos]->Info.Config, config, sizeof(WHT_I2C_BUS_Config_t));
        WHT_I2C_BUS_Init((WHT_I2C_BUS_t*)WHT_I2C_BUS[Pos]);
        return (WHT_I2C_BUS_t*)WHT_I2C_BUS[Pos];
    }
    return NULL;
}
/*注销软件I2C总线*/
static void WHT_I2C_BUS_Unregister(WHT_I2C_BUS_t* bus)
{
    for (size_t i = 0; i < sizeof(WHT_I2C_BUS) / sizeof(WHT_I2C_BUS[0]); i++)
    {
        if (WHT_I2C_BUS[i] == WHT_BUS)
        {
            WHT_I2C_BUS[i] = NULL;
            free(WHT_BUS);
			break;
        }
    }
}

/*全局常量*/
const WHT_I2C_BUS_OPS_t WHT_I2C_BUS_OPS =
{
    .Register         = WHT_I2C_BUS_Register,
    .Unregister       = WHT_I2C_BUS_Unregister,
    .Set_Rate         = WHT_I2C_BUS_Set_Rate,
    .Scan_Mount_Count = WHT_I2C_BUS_Scan_Mount_Count,
    .Receive_EN       = WHT_I2C_BSP_Receive_Cmd,
    .Read_Write       = WHT_I2C_BUS_Read_Write,
    .Read_Write_IT    = WHT_I2C_BUS_Read_Write_IT,
    .Read_Write_DMA   = WHT_I2C_BUS_Read_Write_DMA,
};




/*I2C事件回调函数*/
static void WHT_I2C_BSP_EV_IRQHandler(WHT_I2C_BUS_Private_t* BUS, unsigned int* Count)
{
    I2C_STAT0(BUS->I2C_BUS);
    I2C_STAT1(BUS->I2C_BUS);
    switch (BUS->Master_State_Code)
    {
    case I2C_Master_Start:
        i2c_master_addressing(BUS->I2C_BUS, BUS->Cache->Addr_7Bit << 1, I2C_TRANSMITTER);
        BUS->Master_State_Code = I2C_Master_Write_Addr;
        *Count = 0;
        break;
    case I2C_Master_Restart:
        i2c_master_addressing(BUS->I2C_BUS, BUS->Cache->Addr_7Bit << 1, I2C_RECEIVER);
        BUS->Master_State_Code = I2C_Master_Read_Addr;
        *Count = 0;
        break;
    case I2C_Master_Write_Addr:
        if (BUS->Cache->Cmd_Count < 1)
        {
            i2c_stop_on_bus(BUS->I2C_BUS);//send stop
            WHT_I2C_BSP_User_IT_Callback(BUS);
            break;
        }
        else
        {
            BUS->Master_State_Code = I2C_Master_Send_Cmd;
        }
        // NO BREAK
    case I2C_Master_Send_Cmd:
        if (*Count == BUS->Cache->Cmd_Count)//cmd 发送完
        {
            *Count = 0;
            if (BUS->Cache->Dir == I2C_Write)//是否发送数据
            {
                BUS->Master_State_Code = I2C_Master_Send_Data;
            }
            else//读取数据
            {
                if (BUS->Cache->Buffer_Count > 0)
                {
                    i2c_data_receive(BUS->I2C_BUS); //clear BTF
                    i2c_start_on_bus(BUS->I2C_BUS);//Send i2c Start
                    BUS->Master_State_Code = I2C_Master_Restart;
                }
                else
                {
                    i2c_stop_on_bus(BUS->I2C_BUS);//send stop
                    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//off all interrupt
                    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV );
                    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
                    WHT_I2C_BSP_User_IT_Callback(BUS);
                }
                break;
            }
        }
        else
        {
            i2c_data_transmit(BUS->I2C_BUS, BUS->Cache->Cmd[(*Count)++]);
            break;
        }
    case I2C_Master_Send_Data:
        if (*Count < BUS->Cache->Buffer_Count)
        {
            i2c_data_transmit(BUS->I2C_BUS, BUS->Cache->Buffer[(*Count)++]);
            if (*Count == BUS->Cache->Buffer_Count)
            {
                i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//off TxE interrupt
            }
        }
        else
        {
            i2c_stop_on_bus(BUS->I2C_BUS);//send stop
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//off all interrupt
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV );
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
            WHT_I2C_BSP_User_IT_Callback(BUS);
        }
        break;
    case I2C_Master_Read_Addr:
        if (BUS->Cache->Buffer_Count == 1)
        {
            i2c_stop_on_bus(BUS->I2C_BUS);
        }
        else
            i2c_ack_config(BUS->I2C_BUS, I2C_ACK_ENABLE);
        i2c_interrupt_enable(BUS->I2C_BUS, I2C_INT_BUF);//on rx interrupt
        BUS->Master_State_Code = I2C_Master_Receive_Data;
        break;
    case I2C_Master_Receive_Data:
        BUS->Cache->Buffer[(*Count)++] = i2c_data_receive(BUS->I2C_BUS);
        if ((*Count + 1) == BUS->Cache->Buffer_Count)//倒数第2个数据接收完成
        {
            i2c_ack_config(BUS->I2C_BUS, I2C_ACK_DISABLE);
            i2c_stop_on_bus(BUS->I2C_BUS);
        }
        if (*Count >= BUS->Cache->Buffer_Count)
        {
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//off all interrupt
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV );
            i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
            WHT_I2C_BSP_User_IT_Callback(BUS);
        }
        break;
    case I2C_Master_DMA_Send_End:
        i2c_stop_on_bus(BUS->I2C_BUS);//send stop
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//OFF All Interrupt
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV );
        i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
        BUS->Master_State_Code = I2C_Master_Start;
        WHT_I2C_BSP_User_IT_Callback(BUS);
        break;
    }
}
/*I2C错误回调函数*/
static void WHT_I2C_BSP_ER_IRQHandler(WHT_I2C_BUS_Private_t* BUS)
{
    if (i2c_interrupt_flag_get(BUS->I2C_BUS, I2C_INT_FLAG_BERR) == SET)
    {
        *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_BUS_Error;
    }
    else if (i2c_interrupt_flag_get(BUS->I2C_BUS, I2C_INT_FLAG_AERR) == SET)
    {
        *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_Slave_No_ACK;
    }
    else if (i2c_interrupt_flag_get(BUS->I2C_BUS, I2C_INT_FLAG_LOSTARB) == SET)
    {
        *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_ARLO_Error;
    }
    else if (i2c_interrupt_flag_get(BUS->I2C_BUS, I2C_INT_FLAG_OUERR) == SET)
    {
        if (BUS->Cache->Dir == I2C_Write)
        {
            *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_Tx_Send_Error;
        }
        else
        {
            *(WHT_I2C_BUS_State_enum*)&BUS->Info.State = I2C_Rx_Over_Error;
        }
    }

    i2c_dma_config(BUS->I2C_BUS, I2C_DMA_OFF); //Off DMA请求
    if (BUS->Master_State_Code == I2C_Master_DMA_Receive_End)
    {
        WHT_DMA_BSP.WHT_Close(&BUS->DMA_Receive_Config);
    }
    else if (BUS->Master_State_Code == I2C_Master_DMA_Send_End)
    {
        WHT_DMA_BSP.WHT_Close(&BUS->DMA_Send_Config);
    }

    i2c_stop_on_bus(BUS->I2C_BUS);
    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_BUF);//Off All Interrupt
    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_EV);
    i2c_interrupt_disable(BUS->I2C_BUS, I2C_INT_ERR);
    i2c_ack_config(BUS->I2C_BUS, I2C_ACK_DISABLE);

    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_AERR);
    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_BERR);
    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_LOSTARB);
    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_OUERR);
    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_PECERR);
    i2c_interrupt_flag_clear(BUS->I2C_BUS, I2C_INT_FLAG_SMBTO);
    BUS->Master_State_Code = I2C_Master_Start;
    WHT_I2C_BSP_User_IT_Callback(BUS);
}


/*I2C1 正常事件中断服务程序*/
void I2C0_EV_IRQHandler(void)
{
    static unsigned int Count;

    WHT_I2C_BSP_EV_IRQHandler(WHT_I2C_BUS[0], &Count);
}
/*I2C1 错误事件中断服务程序*/
void I2C0_ER_IRQHandler(void)
{
    WHT_I2C_BSP_ER_IRQHandler(WHT_I2C_BUS[0]);
}

/*I2C2 正常事件中断服务程序*/
void I2C1_EV_IRQHandler(void)
{
    static unsigned int Count;

    WHT_I2C_BSP_EV_IRQHandler(WHT_I2C_BUS[1], &Count);
}
/*I2C2 错误事件中断服务程序*/
void I2C1_ER_IRQHandler(void)
{
    WHT_I2C_BSP_ER_IRQHandler(WHT_I2C_BUS[1]);
}

/*I2C3 正常事件中断服务程序*/
void I2C2_EV_IRQHandler(void)
{
    static unsigned int Count;

    WHT_I2C_BSP_EV_IRQHandler(WHT_I2C_BUS[2], &Count);
}
/*I2C3 错误事件中断服务程序*/
void I2C2_ER_IRQHandler(void)
{
    WHT_I2C_BSP_ER_IRQHandler(WHT_I2C_BUS[2]);
}
